package cn.ug.analyse.service.impl;

import cn.ug.analyse.bean.ChannelBean;
import cn.ug.analyse.bean.ChannelStaffBean;
import cn.ug.analyse.bean.GrossBean;
import cn.ug.analyse.bean.RewardPlanBean;
import cn.ug.analyse.mapper.entity.AssessEntity;
import cn.ug.analyse.mapper.entity.ChannelPeriodEntity;
import cn.ug.analyse.mapper.entity.InviteEntity;
import cn.ug.analyse.service.AssessService;
import cn.ug.analyse.service.ChannelService;
import cn.ug.analyse.service.ChannelStaffService;
import cn.ug.analyse.service.InvestService;
import cn.ug.analyse.service.InviteService;
import cn.ug.analyse.service.SettleService;
import cn.ug.util.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dozer.DozerBeanMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhaohg
 * @date 2018/08/13.
 */
@Service
public class StatServiceImpl implements cn.ug.analyse.service.StatService {
    private static Log                 log = LogFactory.getLog(SettleServiceImpl.class);
    @Resource
    private        ChannelService      channelService;
    @Resource
    private        ChannelStaffService channelStaffService;
    @Resource
    private        InviteService       inviteService;
    @Resource
    private        InvestService       investService;
    @Resource
    private        AssessService       assessService;
    @Resource
    private        DozerBeanMapper     dozerBeanMapper;
    @Resource
    private        SettleService       settleService;


    public void statChannelData(Date date) {

        //1、获取所有渠道
        List<ChannelBean> channelList = channelService.findListByDate(date);
        if (CollectionUtils.isNotEmpty(channelList)) {
            Iterator<ChannelBean> iterator = channelList.iterator();
            //2、循环渠道
            while (iterator.hasNext()) {
                ChannelBean bean = iterator.next();
                if (bean.getIsEnable() == 0 || bean.getPlanStep() == null || bean.getOneInviteReward() == null) {
                    continue;
                }
                //处理渠道成员 1级 2级 及绑卡关系映射
                this.statChannelStaffData(bean, date);
                //渠道成员业绩 处理绑卡用户数量 交易数据
                this.statBindCardUserTrade(bean, date);
                //根据奖励方案周期, 每个周期生成一个周期累计绑卡(绑卡总数和奖励总数)、总交易量、奖励金额(根据奖励方案的)结算记录
                this.statChannelPeriod(bean, date);
            }
        }
    }

    private void statChannelStaffData(ChannelBean bean, Date date) {
        //2.1 渠道的所有成员
        List<ChannelStaffBean> staffList = channelStaffService.findListByChannelId(bean.getId());
        if (CollectionUtils.isNotEmpty(staffList)) {

            Set<Long> staffIds = staffList.stream().map(ChannelStaffBean::getId).collect(Collectors.toSet());
            //查询 邀请的一级用户
            List<InviteEntity> firstList = investService.findYesterdayFirstList(Lists.newArrayList(staffIds));

            //昨天所有绑卡用户
            List<InviteEntity> allList = new ArrayList<>(firstList);
            if (CollectionUtils.isNotEmpty(firstList)) {
                //userId
                Map<String, InviteEntity> firstMap = firstList.stream().collect(Collectors.toMap(InviteEntity::getUserId, InviteEntity -> InviteEntity));

                Set<String> userIds = firstList.stream().map(InviteEntity::getUserId).collect(Collectors.toSet());
                //查询 邀请的二级用户
                List<InviteEntity> secondList = investService.findYesterdaySecondList(Lists.newArrayList(userIds));

                List<InviteEntity> twoList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(secondList)) {
                    Iterator<InviteEntity> iterator = secondList.iterator();
                    while (iterator.hasNext()) {
                        InviteEntity entity = iterator.next();
                        InviteEntity invite = firstMap.get(entity.getInviteId());
                        entity.setChannelId(bean.getId());
                        entity.setSuperiorId(invite == null ? null : invite.getInviteId());
                        entity.setSuperiorName(invite == null ? null : invite.getInviteName());

                        twoList.add(entity);
                    }
                }
                allList.addAll(twoList);
            }

            if (CollectionUtils.isNotEmpty(allList)) {
                int total = allList.size();
                int size = 100;
                for (int i = 0; i < total; i += 100) {
                    if (i + 100 > total) {        //作用为index最后没有100条数据则剩余几条newList中就装几条
                        size = total - i;
                    }
                    List<InviteEntity> subUserList = allList.subList(i, i + size);
                    //批量统计 每次统计 index 个用户
                    this.statChannelBindUserData(subUserList, date);
                }
            }
        }

    }

    private void statChannelBindUserData(List<InviteEntity> list, Date date) {
        Set<String> ids = list.stream().map(InviteEntity::getUserId).collect(Collectors.toSet());
        Map<String, InviteEntity> map = list.stream().collect(Collectors.toMap(InviteEntity::getUserId, InviteEntity -> InviteEntity));

        List<InviteEntity> bindCardList = investService.findYesterdayBindCardList(Lists.newArrayList(ids), date);
        if (CollectionUtils.isNotEmpty(bindCardList)) {
            Iterator<InviteEntity> iterator = bindCardList.iterator();
            while (iterator.hasNext()) {
                InviteEntity next = iterator.next();
                InviteEntity entity = map.get(next.getUserId());
                entity.setBindCardType(next.getBindCardType());
                entity.setBindCardDate(date);

                inviteService.insert(entity);
            }
        }
    }

    //渠道成员业绩
    private void statBindCardUserTrade(ChannelBean bean, Date date) {
        //昨天交易情况
        //pay_product_order
        List<ChannelStaffBean> staffList = channelStaffService.findListByChannelId(bean.getId());
        if (CollectionUtils.isEmpty(staffList)) {
            return;
        }

        Iterator<ChannelStaffBean> staffIterator = staffList.iterator();
        while (staffIterator.hasNext()) {//todo 怎么优化？
            ChannelStaffBean staff = staffIterator.next();

            //查询昨天渠道成员下的 一级 和 二级交易量和年化
            List<InviteEntity> allUserList = inviteService.findAllUserListByStaffId(staff.getId());

            List<InviteEntity> firstBindList = allUserList.stream().filter(
                    a -> a.getInviteType() == 1 && DateUtil.format(a.getBindCardDate(), "yyyyMMdd").equals(DateUtil.format(date, "yyyyMMdd"))
            ).collect(Collectors.toList());
            List<InviteEntity> secondBindList = allUserList.stream().filter(
                    a -> a.getInviteType() == 2 && DateUtil.format(a.getBindCardDate(), "yyyyMMdd").equals(DateUtil.format(date, "yyyyMMdd"))
            ).collect(Collectors.toList());


            List<InviteEntity> firstUserList = allUserList.stream().filter(
                    a -> a.getInviteType() == 1
            ).collect(Collectors.toList());
            List<InviteEntity> secondUserList = allUserList.stream().filter(
                    a -> a.getInviteType() == 2
            ).collect(Collectors.toList());

            GrossBean firstTrade = null;
            GrossBean secondTrade = null;
            if (CollectionUtils.isNotEmpty(firstUserList)) {
                Set<String> firstUserIds = firstUserList.stream().map(InviteEntity::getUserId).collect(Collectors.toSet());
                firstTrade = investService.findYesterdayFirstListByUserIds(Lists.newArrayList(firstUserIds), date);
            }
            if (CollectionUtils.isNotEmpty(secondUserList)) {
                Set<String> secondUserIds = secondUserList.stream().map(InviteEntity::getUserId).collect(Collectors.toSet());
                secondTrade = investService.findYesterdayFirstListByUserIds(Lists.newArrayList(secondUserIds), date);
            }

            //查询昨天 一级 和 二级绑卡数量
//            int firstBindCardNum = inviteService.findYesterdayFirstBindCardNumByStaffId(staff.getId(), date);
//            int secondBindCardNum = inviteService.findYesterdaySecondBindCardNumByStaffId(staff.getId(), date);

            AssessEntity assess = new AssessEntity();
            assess.setChannelId(bean.getId());//渠道id
            assess.setStaffId(staff.getId());//成员id
            assess.setFirstBindCardNum(CollectionUtils.isNotEmpty(firstBindList) ? firstBindList.size() : 0);   //一级绑卡数量
            assess.setFirstBindCardAmount(BigDecimal.valueOf(assess.getFirstBindCardNum()).multiply(bean.getOneInviteReward()));
            assess.setSecondBindCardNum(CollectionUtils.isNotEmpty(secondBindList) ? secondBindList.size() : 0);//二级绑卡数量
            BigDecimal secondBindCardAmount = BigDecimal.valueOf(assess.getSecondBindCardNum()).multiply(bean.getTwoInviteReward());
            assess.setSecondBindCardAmount(secondBindCardAmount);
            assess.setFirstTradeNum(firstTrade == null ? BigDecimal.ZERO : firstTrade.getAmount());//一级交易量
            assess.setFirstAnnual(firstTrade == null ? BigDecimal.ZERO : firstTrade.getAnnual());//一级年化
            assess.setSecondTradeNum(secondTrade == null ? BigDecimal.ZERO : secondTrade.getAmount());//二级交易量
            assess.setSecondAnnual(secondTrade == null ? BigDecimal.ZERO : secondTrade.getAnnual());//二级年化
            assess.setTradeDate(date);//昨天的日期
            if (this.checkParams(assess)) {
                assessService.insert(assess);//添加到业绩表
            }
        }
    }
    private boolean checkParams(AssessEntity assess) {

        if (assess.getFirstBindCardNum() > 0) return true;
        if (assess.getSecondBindCardNum() > 0) return true;
        if (assess.getFirstBindCardAmount().compareTo(BigDecimal.ZERO) > 0) return true;
        if (assess.getSecondBindCardAmount().compareTo(BigDecimal.ZERO) > 0) return true;
        if (assess.getFirstTradeNum().compareTo(BigDecimal.ZERO) > 0) return true;
        if (assess.getSecondTradeNum().compareTo(BigDecimal.ZERO) > 0) return true;
        if (assess.getFirstAnnual().compareTo(BigDecimal.ZERO) > 0) return true;
        return assess.getSecondAnnual().compareTo(BigDecimal.ZERO) > 0;
    }


    //结算历史 结算操作记录
    private void statChannelPeriod(ChannelBean bean, Date date) {
        LocalDate localDate = DateUtil.dateToLocalDate(date);

        //判断昨天是否在是一个周期的最后一天
        LocalDate preMonthLastDay = localDate.with(TemporalAdjusters.lastDayOfMonth());
//        if (bean.getPeriod() == 1 ){//&& localDate == preMonthLastDay) {//如果昨天是上个月最后一天
        if (bean.getPeriod() == 1 && localDate == preMonthLastDay) {//如果昨天是上个月最后一天
            //统计渠道周期累计奖励记录

            Date startDate = DateUtil.localDateToDate(localDate.with(TemporalAdjusters.firstDayOfMonth()));
            Date endDate = DateUtil.localDateToDate(preMonthLastDay);
            this.getTotalReward(bean, startDate, endDate);//一个周期总奖励

            return;
        }

        if (bean.getPeriod() == 2 && date.getTime() == date.getTime()) {//如果昨天是上个季度最后一天
            //统计渠道周期累计奖励记录

            Date startDate = DateUtil.getQuarterStartTime(date);
            Date endDate = DateUtil.getQuarterEndTime(date);
            this.getTotalReward(bean, startDate, endDate);//一个周期总奖励

            return;
        }

        LocalDate yearLastDay = localDate.with(TemporalAdjusters.lastDayOfYear());
        if (bean.getPeriod() == 3 && localDate == yearLastDay) {//如果昨天是去年的最后一天
            //统计渠道周期累计奖励记录

            Date startDate = DateUtil.localDateToDate(localDate.with(TemporalAdjusters.firstDayOfYear()));
            Date endDate = DateUtil.localDateToDate(yearLastDay);
            this.getTotalReward(bean, startDate, endDate);//一个周期总奖励

            return;
        }
        return;
    }

    /**
     * 计算渠道总奖励
     * 添加周期奖励记录
     * 累加到渠道总奖励
     *
     * @param bean
     * @param startDate
     * @param endDate
     * @return
     */
    private void getTotalReward(ChannelBean bean, Date startDate, Date endDate) {
        ChannelPeriodEntity periodEntity = settleService.getChannelPeriodByDate(bean.getId(), startDate, endDate);
        if (periodEntity != null) {
            return;
        }
//        try {
//            startDate = DateUtil.parse("2018-08-01", "yyyy-MM-dd");
//            endDate = DateUtil.parse("2018-08-31", "yyyy-MM-dd");
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
        BigDecimal totalAmount = BigDecimal.ZERO;

        AssessEntity entity = assessService.findChannelTotalAccess(bean.getId(), startDate, endDate);//获取上一周期的渠道总业绩
        if(entity == null) return;
        BigDecimal firstBindCardTotalAmount = entity.getFirstBindCardAmount();//一级绑卡奖励
        BigDecimal secondBindCardTotalAmount = entity.getSecondBindCardAmount();//二绑绑卡奖励
        totalAmount = totalAmount.add(firstBindCardTotalAmount).add(secondBindCardTotalAmount);//绑卡总奖励

        BigDecimal firstTradeNum = entity.getFirstTradeNum();//一级交易量
        BigDecimal secondTradeNum = entity.getSecondTradeNum();//二级交易量

        String jsonStr = bean.getPlanStep();//奖励阶梯
        List<RewardPlanBean> planList = JSONObject.parseArray(jsonStr, RewardPlanBean.class);

        BigDecimal firstTradeAmount = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(planList)) {
            for (RewardPlanBean reward : planList) {
                BigDecimal amount = firstTradeNum;

                BigDecimal tradeLower = BigDecimal.valueOf(reward.getTradeLower() == null ? 0 : reward.getTradeLower() * 10000);//低
                BigDecimal tradeUpper = BigDecimal.valueOf(reward.getTradeUpper() == null ? 0 : reward.getTradeUpper() * 10000);//高
                if (firstTradeNum.compareTo(tradeUpper) > 0) {
                    amount = tradeUpper;
                }
                if (amount.compareTo(tradeLower) >= 0) {
                    BigDecimal rew = reward.getReward() == null ? BigDecimal.ZERO : reward.getReward().divide(BigDecimal.valueOf(100));
                    BigDecimal lower = amount.subtract(tradeLower);
                    firstTradeAmount = firstTradeAmount.add(lower.multiply(rew));//一级交易阶梯奖励
                }
            }
        }

        BigDecimal secondTradeAmount = BigDecimal.ZERO;
        if (bean.getSecondReward() != null) {
            secondTradeAmount = secondTradeNum.multiply(bean.getSecondReward().divide(BigDecimal.valueOf(100)))//二级交易奖励
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
        }

        totalAmount = totalAmount.add(secondTradeAmount).add(firstTradeAmount.setScale(2, BigDecimal.ROUND_HALF_UP));

        //周期奖励记录并累加到渠道
        ChannelPeriodEntity period = dozerBeanMapper.map(entity, ChannelPeriodEntity.class);
        period.setChannelId(bean.getId());
        period.setFirstTradeAmount(firstTradeAmount);
        period.setSecondTradeAmount(secondTradeAmount);
        period.setRewardTotalAmount(totalAmount);
        period.setStartDate(startDate);
        period.setEndDate(endDate);
        settleService.addChannelPeriod(period);
    }


}
